package com.soft.bams.service;

import com.soft.bams.dao.ArrayDao;
import com.soft.bams.dao.IDao;
import com.soft.bams.entity.*;
import com.soft.bams.exception.*;
import com.soft.bams.vo.RankVO;

import javax.swing.*;
import java.util.TreeSet;


/**
 * @author chenmin
 * @desc 业务逻辑层
 * @date 2025/4/18
 */
public class Bank {

    //关联
    private IDao<Account, Account[]> dao;

    private Bank(){
        //面向接口编程，可插拔式编程、耦合度降低
        dao = new ArrayDao();
    }

    //Bank单例模式
    private static Bank bank;

    public static Bank getInstance(){
        if(bank==null){
            bank = new Bank();
        }
        return bank;
    }


    public Account register(String password, String repassword, String name, String personID, String email, int type)
            throws NotFoundException, RegisterException {
        if(password==null || repassword==null || password.equals("") || repassword.equals("")){

            throw new NotFoundException("密码不能为空");
        }

        Account acc = null;
        if(password.equals(repassword)){

            Long id = dao.createId();
            if(id!=-1L){
                switch (type){
                    case 0:
                        //储蓄账户  多态：父类的引用指向子类的实例
                        acc = new SavingAccount(id , password , name , personID , email , 0.0);
                        break;
                    case 1:
                        //信用账户
                        acc = new CreditAccount(id , password , name , personID , email , 0.0 , 1500.0);
                        break;
                    case 2:
                        //可贷款储蓄账户
                        acc = new LoanSavingAccount(id , password , name , personID , email , 0.0 , 0);
                        break;
                    case 3:
                        //可贷款信用账户
                        acc = new LoanCreditAccount(id , password , name , personID , email , 0.0 , 1500.0 , 0);
                        break;
                    default:
                        System.out.println("账户类型不匹配");
                        break;
                }
            }else{
                //System.out.println("开户失败！");
                throw new RegisterException("开户失败");
            }

            //注册
            if(acc!=null){
                boolean inserted = dao.insert(acc);
                if(inserted){

                    JOptionPane.showMessageDialog(null , "开户成功！");
                }else{

                    throw new RegisterException("开户失败！");
                }
            }
        }else{
            //System.out.println("两次密码需要输入一致！");
            throw new RegisterException("两次密码需要输入一致");
        }
        return acc;
    }



    public Account login(Long id, String password) throws NotFoundException, LoginException {
        if(id==null || password==null || id.equals("") || password.equals("")){

            throw new NotFoundException("用户ID和密码不能为空");
        }
        //查询
        Account acc = dao.selectOne(id, password);
        if(acc!=null){
            //System.out.println("登录成功！");
            JOptionPane.showMessageDialog(null , "登录成功！");
        }else{
            //System.out.println("登录失败");
            throw new LoginException("登录失败");
        }
        return acc;
    }


    public Account deposit(Long id, double money) throws NotFoundException, MoneyException {
        if(id==null){
            throw new NotFoundException("账户ID不能为空");
        }
        if(money<=0){
            throw new MoneyException("操作的金额不能<=0");
        }
        //查询
        Account acc = dao.selectOne(id);
        if(acc!=null){
            //存款
            acc.deposit(money);
        }else{
            //System.out.println("账户ID不存在！");
            throw new NotFoundException("账户ID不存在！");
        }
        return acc;
    }

    public Account withdraw(Long id, String password, double money)
            throws NotFoundException, MoneyException, BalanceNotEnoughException {
        if(id==null || password==null || password.equals("")){
            /*System.out.println("账户ID或密码不能为空 或 操作的金额不能<=0");
            return null;*/
            throw new NotFoundException("账户ID或密码不能为空");
        }
        if(money<=0){
            throw new MoneyException("操作的金额不能<=0");
        }
        //查询
        Account acc = dao.selectOne(id,password);
        if(acc!=null){
            //取款
            //多态：编译看左边(Account)，运行看右边（SavingAccount、CreditAccount）
            acc.withdraw(money);
        }else{
            //System.out.println("账户ID与密码不匹配！");
            throw new NotFoundException("账户ID与密码不匹配！");
        }
        return acc;
    }



    public Account updateCeiling(Long id, String password, double money)
            throws NotFoundException, MoneyException, TypeException {
        if(id==null || password==null || password.equals("")){
            throw new NotFoundException("账户ID或密码不能为空");
        }
        if(money<=0){
            throw new MoneyException("操作的金额不能<=0");
        }
        //查询
        Account acc = dao.selectOne(id, password);
        if(acc!=null){

            if(acc instanceof CreditAccount){

                ((CreditAccount) acc).setCeiling(money);
                JOptionPane.showMessageDialog(null , "修改透支额度成功！");
            }else{

                throw new TypeException("当前银行卡类型不支持修改透支额度");
            }
        }else{

            throw new NotFoundException("当前账户ID和密码不匹配!");
        }
        return acc;
    }



    public boolean transfer(Long from, String passwordFrom, Long to, double money)
            throws NotFoundException, MoneyException, TransferException, BalanceNotEnoughException {
        if(from==null || passwordFrom==null || passwordFrom.equals("") || to==null ){
            throw new NotFoundException("转出账户 或 转入账户不能为空");
        }
        if(money<=0){
            throw new MoneyException("操作的金额不能<=0");
        }
        if(from.equals(to)){

            throw new TransferException("转出账户 和 转入账户不能是同一个账户");
        }

        Account accFrom = dao.selectOne(from, passwordFrom);
        if(accFrom!=null){
            //查询转入账户
            Account accTo = dao.selectOne(to);
            if(accTo!=null){

                if((accFrom instanceof SavingAccount) && (accFrom.getBalance()<money)){

                    throw new BalanceNotEnoughException("转出账户余额不足！");
                }


                if((accFrom instanceof CreditAccount) && (accFrom.getBalance() + ((CreditAccount) accFrom).getCeiling()<money)){

                    throw new BalanceNotEnoughException("转出账户余额不足！");
                }


                accFrom.withdraw(money);
                accTo.deposit(money);

                JOptionPane.showMessageDialog(null , "转账成功！");
                return true;
            }else{

                throw new NotFoundException("转入账户不存在");
            }
        }else{

            throw new NotFoundException("转出账户不存在");
        }
    }


    public Account requestLoan (Long id , double money)
            throws NotFoundException, MoneyException, TypeException {
        if(id==null){
            throw new NotFoundException("账户ID不能为空");
        }
        if(money<=0){
            throw new MoneyException("操作的金额不能<=0");
        }
        //查询账户
        Account acc = dao.selectOne(id);
        if(acc!=null){
            //判断当前账户是否支持贷款操作
            if(acc instanceof Loanable){
                //若支持，即向下造型（强制转换）
                ((Loanable)acc).requestLoan(money);
                JOptionPane.showMessageDialog(null , "贷款成功！");
            }else{
                //System.out.println("当前账户类型不支持贷款操作！");
                throw new TypeException("当前账户类型不支持贷款操作!");
            }
        }else{
            //System.out.println("账户ID不存在！");
            throw new NotFoundException("账户ID不存在!");
        }
        return acc;
    }

    public Account payLoan(Long id , double money)
            throws NotFoundException, MoneyException, TypeException {
        if(id==null){
            throw new NotFoundException("账户ID不能为空");
        }
        if(money<=0){
            throw new MoneyException("操作的金额不能<=0");
        }
        //查询
        Account acc = dao.selectOne(id);
        if(acc!=null){
            //判断当前账户是否支持还贷操作
            if(acc instanceof Loanable){
                //若支持，即向下造型（强制转换）
                ((Loanable)acc).payLoan(money);
                JOptionPane.showMessageDialog(null , "还贷成功！");
            }else {
                //System.out.println("当前账户类型不支持还贷操作！");
                throw new TypeException("当前账户类型不支持还贷操作！");
            }
        }else{
            //System.out.println("账户ID不存在！");
            throw new NotFoundException("账户ID不存在！");
        }
        return acc;
    }

    //---------------------------------------------- 统计 --------------------------------------------------
    //1.统计银行所有账户余额总数
    public double totalBalance(){
        double sum = 0.0;
        for (Account account : dao.selectAll()) {
            if(account!=null){
                sum+=account.getBalance();
            }
        }
        return sum;
    }

    //2.统计所有信用账户透支额度总数
    public double totalCeiling(){
        double sum = 0.0;
        for (Account acc : dao.selectAll()) {
            if(acc!=null){
                //可能会出现ClassCastException 类型转换异常
                if(acc instanceof CreditAccount){
                    sum += ((CreditAccount)acc).getCeiling();
                }
            }
        }
        return sum;
    }

    //3.统计所有账户贷款的总额(total)
    public double totalLoanAmount(){
        double sum = 0.0;
        for (Account acc : dao.selectAll()) {
            if(acc!=null){
                if(acc instanceof LoanSavingAccount){
                    sum+=((LoanSavingAccount) acc).getLoanAmount();
                }
                if(acc instanceof LoanCreditAccount){
                    sum+=((LoanCreditAccount) acc).getLoanAmount();
                }
            }
        }
        return sum;
    }

    public TreeSet<RankVO> rank() {
        return null;
    }
}
